<!-- 在script 标签上使用setup，可以不用再使用return的写法了 -->
<!-- 其中 setup 标记的 script 必须是单独的，不能和export等其他共用 -->
<!-- 可以使用  npm i vite-plugin-vue-setup-extend -D 插件替换下面的写法，直接将组件名称定义写到script的name属性上 -->
<!--<script lang="ts">
export default {
  name: 'Person',
}
</script>-->

<!-- 可以使用  npm i vite-plugin-vue-setup-extend -D 插件替换下面的写法，直接将组件名称定义写到script的name属性上 -->
<!-- 如果没有定义组件名称，没有给script写name定义组件名称的话，默认就是组件的名称。 -->
<script setup lang="ts" name="Person">
import { reactive, watch } from 'vue'

let person = reactive({
  name: '张三',
  age: 18,
})

// 用于测试深度监视
let object = reactive({
  a: {
    b: {
      c: 666,
    },
  },
})

// 换人计划
function changePerson() {
  let zhangsansan = {
    name: '张珊珊',
    age: 18,
  }
  // reactive不支持直接修改，可以使用Object.assign进行修改整个对象。其中使用Object.assign是进行属性值的替换，而ref使用的是整个对象的替换
  Object.assign(person, zhangsansan)
}

// 监视，情况三：监视【reactive】定义的【对象类型】数据，且默认是开启深度监视的
watch(
  person,
  (newValue, oldValue) => {
    // 若修改整个ref定义的对象，newValue 是新值， oldValue 是旧值，因为不是同一个对象了。
    // 若修改的是ref定义的对象中的属性，newValue 和 oldValue 都是新值，因为它们是同一个对象。
    console.log('person变化了', newValue, oldValue)
  },
  {
    deep: true, // 深度监视
    immediate: true, // 立即监视
  },
)

// 测试深度监视，默认开启了深度监视的。
watch(object, (newValue, oldValue) => {
  console.log('Obj变化了', newValue, oldValue)
})
</script>

<template>
  <div class="person">
    <h1>情况三：监视【reactive】定义的【对象类型】数据</h1>
    <h1>姓名：{{ person.name }}</h1>
    <h1>年龄：{{ person.age }}</h1>
    <button @click="person.name += '!'">姓名变幻</button>
    <button @click="person.age += 1">年龄变幻</button>
    <button @click="changePerson()">换人计划</button>

    <hr />
    <h2>测试：{{ object.a.b.c }}</h2>
    <button @click="object.a.b.c = 999">修改object.a.b.c</button>
  </div>
</template>

<style scoped>
.person {
  background-color: #dab649;
  box-shadow: 0 0 10px;
  border-radius: 10px;
  padding: 20px;
}

button {
  margin: 0 10px;
}
</style>
